﻿using System;
using DesignByContract;
using MadMediaManager.Core.Interfaces.DataAccess;
using MadMediaManager.Core.Interfaces.DataAccess.Repositories;
using MadMediaManager.DataAccess.Repositories;
using NHibernate;

namespace MadMediaManager.DataAccess
{
    public class NHibernateDbContext : IDbContext
    {
        private ISession _session;
        public NHibernateDbContext(ISession session)
        {
            Check.Require(session != null, "session cannot be null");
            _session = session;
        }

        public void Dispose()
        {
            DisposeAndNullify(ref _softwareIsoRepository);
            DisposeAndNullify(ref _movieIsoRepository);
            DisposeAndNullify(ref _televisionIsoRepository);
            DisposeAndNullify(ref _session);
        }

        public void SubmitChanges()
        {
            _session.Flush();
        }

        public void Refresh(object entity)
        {
            _session.Refresh(entity);
        }

        #region Repositories

        private ISoftwareIsoRepository _softwareIsoRepository;
        public ISoftwareIsoRepository SoftwareIsos
        {
            get { return _softwareIsoRepository ?? (_softwareIsoRepository = new SoftwareIsoRepository(_session)); }
        }

        private IMovieIsoRepository _movieIsoRepository;
        public IMovieIsoRepository MovieIsos
        {
            get { return _movieIsoRepository ?? (_movieIsoRepository = new MovieIsoRepository(_session)); }
        }

        private ITelevisionIsoRepository _televisionIsoRepository;
        public ITelevisionIsoRepository TelevisionIsos
        {
            get { return _televisionIsoRepository ?? (_televisionIsoRepository = new TelevisionIsoRepository(_session)); }
        }

        private IUnknownIsoRepository _unknownIsoRepository;
        public IUnknownIsoRepository UnknownIsos
        {
            get { return _unknownIsoRepository ?? (_unknownIsoRepository = new UnknownIsoRepository(_session)); }
        }

        #endregion

        private static void DisposeAndNullify<T>(ref T disposable) where T : class, IDisposable
        {
            if (disposable == null) return;

            disposable.Dispose();
            disposable = default(T);
        }
    }
}
